#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;
/*
1、配置RCC，把涉及的外设时钟都打开；
2、配置GPIO，选择端口为输入模式；
3、配置AFIO，选择使用的GPIO连接到EXTI；
4、配置EXTI，选择边沿触发方式（上、下、双边），选择触发响应方式（中断、事件响应）；
5、配置NVIC，优先级分组，指定中断通道，给中断选择合适的优先级
最后通过NVIC，外部中断信号就能进入CPU了，CPU收到中断信号才能跳转到中断函数里面执行中断程序
*/
void Encoder_Init(void)
{
/*1、配置RCC*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//开启GPIO和AFIO的时钟
	//EXTI时钟一直都是打开的，无需配置
	//NVIC在内核（“皇宫”）里面，RCC管不到，无需配置
/*2、配置GPIO*/
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//EXTI输入线：悬空，上拉（默认高电平），下拉（默认低电平）下拉三选一
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;//PB0,PB1
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
/*3、配置AFIO*/
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//配置AFIO选择PB0引脚连接EXTI
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);//配置AFIO选择PB1引脚连接EXTI
/*4、配置EXTI*/
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//选触发响应方式为中断触发，而非事件触发
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//选触发方式选择下降沿触发
	EXTI_Init(&EXTI_InitStructure);
/*5、配置NVIC*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组方式_0~_5：0，4~4，0中选择2，2：0~3，0~3
	
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//指定中断通道EXIT0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//排队优先级高到低0~3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//抢占优先级高到低0~3
	NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//指定中断通道EXIT1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//排队优先级高到低0~3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//抢占优先级高到低0~3
	NVIC_Init(&NVIC_InitStructure);
}

int16_t Encoder_Get(void)
{
	int16_t Temp;
	Temp = Encoder_Count;
	Encoder_Count = 0;
	return Temp;
}
/*江科大编码器 VCC GND C   A  */
/* 我的编码器  VCC GND S1  S2 */
/*     STM32   3V3 GND PB1 PB0*/
/*****正反转时，S1和S2相位超前或滞后1/4个周期，两相都是  “边沿对应电平”  的组合*****/
void EXTI1_IRQHandler(void)//函数名要在启动文件Start_md.s中找到，对应所选中断通道
{
	if (EXTI_GetITStatus(EXTI_Line1) == SET)//先进行中断标志位的判断，确保是所选中断源触(EXIT1)发这个函数
	{
		/*********************S1相:下降沿 且 S2相:低电平 条件下**********************/
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
		{
			Encoder_Count++;//正转
		}
		EXTI_ClearITPendingBit(EXTI_Line1);//清除中断标志位
	}
}

void EXTI0_IRQHandler(void)//函数名要在启动文件Start_md.s中找到，对应所选中断通道
{
	if (EXTI_GetITStatus(EXTI_Line0) == SET)//先进行中断标志位的判断，确保是所选中断源触(EXIT0)发这个函数
	{
		/*********************S1相:低电平 且 S2相:下降沿 条件下**********************/
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			Encoder_Count--;//反转
		}
		EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志位
	}
}
